package com.bjpowernode.threadpool.extend;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

/**
 * 自定义线程池对jdk线程池扩展
 *
 */
public class MyThreadPoolExecutor extends ThreadPoolExecutor {

    private static final Logger logger = LoggerFactory.getLogger(MyThreadPoolExecutor.class);

    private final ThreadLocal<Long> startTimeThreadLocal = new ThreadLocal<>();

    public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
    }

    public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        startTimeThreadLocal.set(System.currentTimeMillis());
        logger.info("线程-{}-任务开始执行时间：{}", t.getName() + t.getId(), startTimeThreadLocal.get());
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        long endTime = System.currentTimeMillis();
        long executeTime = endTime - startTimeThreadLocal.get();
        logger.info("线程-{}-任务执行结束时间：{}ms", Thread.currentThread().getName() + Thread.currentThread().getId(), executeTime);
    }

    @Override
    protected void terminated() {
        super.terminated();
        startTimeThreadLocal.remove();
        logger.info("线程-{}-执行完毕退出.", Thread.currentThread().getName() + Thread.currentThread().getId());
        //TODO 发个通知
    }

    public static void main(String[] args) {
        MyThreadPoolExecutor myThreadPoolExecutor = new MyThreadPoolExecutor(
                8,
                16,
                15,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(512),
                Executors.defaultThreadFactory(),
                new AbortPolicy());

        for (int i = 0; i < 5; i++) {
            myThreadPoolExecutor.execute(() -> {
                logger.info("线程-{}-正在执行......", Thread.currentThread().getName() + Thread.currentThread().getId());
            });
        }
        //关闭线程池
        //myThreadPoolExecutor.shutdown();
    }
}